/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://code.google.com/p/dylab/

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

#ifndef __dylab_NodeComplex_h__
#define __dylab_NodeComplex_h__

//===========================================================================================
#include <dylab/utils/types/DynamicCast.h>
#include <dylab/utils/EmptyClass.h>
#include <dylab/utils/topology/SimplicalComplex.h>

//===========================================================================================
namespace dylab {
            
    /** NodeComplex is 0-simplical complex.
     */   
    template <
        class _NodeSimplexDataT = EmptyClass
    >
    class NodeComplex 
        : public SimplicalComplex
    {           
    public:
        // only for convenience (and typing ;-)
        typedef typename NodeComplex<_NodeSimplexDataT> NodeComplexT;
    public:
        //-----------------------------------------------------------------------------
        /// NodeSimplex is 0-simplex.
        class NodeSimplex 
            : public Simplex
            , public _NodeSimplexDataT
        {      
        public:
            static const order_t ORDER = ORDER_0;
        public:
            /** default constructor.
             */
            NodeSimplex(id_t id, NodeComplexT * complex)
                : Simplex(ORDER, id, complex)
                    { }
            /**
             */
            virtual ~NodeSimplex()
                    { }
            /** 
             */
            NodeComplexT * getNodeComplex()
                    { return DynamicCast<SimplicalComplex, NodeComplexT>(getComplex()); }
        };
        //-----------------------------------------------------------------------------
    public:
        // only for convenience (and typing ;-)
		typedef typename NodeSimplex::id_t nodeSimplexID_t;
        /// declare node container
        typedef HashObjContainer<nodeSimplexID_t, NodeSimplex> NodeSimplexMap;

    public:
        /// builds a map of all simplex nodes 
        /// (i.e., 0-simplices, that are direct or undirect sub-simplices of the specified simplex)
        class SimplexNodes
        {
        private:
            Simplex * mSourceSimplex;
            NodeSimplexMap mNodes;
        public:
            SimplexNodes(Simplex * simplex)
                : mSourceSimplex(simplex), mNodes(false)
                    { 
                        DYLAB_ASSERT(mSourceSimplex != NULL);
                        DYLAB_ASSERT(mSourceSimplex->getOrder() > NodeSimplex::ORDER);

                        // TODO
                    }
            virtual ~SimplexNodes()
                    { }
            typename NodeSimplexMap::Iterator nodeIterator()
                    { return NodeSimplexMap::Iterator(mNodes); }
            typename NodeSimplexMap::Reader nodeReader()
                    { return NodeSimplexMap::Reader(mNodes); }
        };
        //-----------------------------------------------------------------------------
    public:

        /**
        */
        NodeComplex()
                { }

        /**
         */           
        virtual ~NodeComplex()
                { }

        /**
         */           
        NodeSimplex * getNode(nodeSimplexID_t nodeID)
                {  return dynamicCast<NodeSimplex>(simplicesReader(NodeSimplex::ORDER).get(nodeID)); }

        /**
         */           
        const NodeSimplex * getNode(nodeSimplexID_t nodeID) const
                {  return dynamicCast<const NodeSimplex>(simplicesReader(NodeSimplex::ORDER).get(nodeID)); }
        /**
         */           
        nodeSimplexID_t generateNodeID()
                { return generateSimplexID(NodeSimplex::ORDER); }
    };
    
}
//===========================================================================================
#endif // __dylab_NodeComplex_h__
